<template>
  <div class="table-log-root">
    <div class="table-container">
      <div class="table-operator-btns">
        <div>
          <el-divider direction="vertical" />
          <el-switch inline-prompt size="default" active-text="全部匹配" inactive-text="部分匹配"
            v-model="tableParams.matchOperator" />
          <el-divider direction="vertical" />
          <el-switch inline-prompt size="default" active-text="开启高亮" inactive-text="关闭高亮"
            v-model="tableParams.highlight" />
          <el-divider direction="vertical" />
          <el-switch inline-prompt size="default" active-text="分数降序" inactive-text="关闭排序"
            v-model="tableParams.sortHitScoreDesc" @change="sortHitScoreDescChange" />
          <el-divider direction="vertical" />
          <el-switch inline-prompt size="default" active-text="时间降序" inactive-text="关闭排序"
            v-model="tableParams.sortTimestampDesc" @change="sortTimestampDescChange" />
          <el-divider direction="vertical" />
        </div>
        <div>
          <el-divider direction="vertical" />
          <el-switch inline-prompt size="default" active-text="优化格式" inactive-text="原始格式"
            v-model="tableParams.originMessage" />
          <el-divider direction="vertical" />
          <el-switch inline-prompt size="default" active-text="定时刷新" inactive-text="关闭刷新" v-model="intervalRefreshAll"
            @change="intervalRefreshAllChange" />
          <el-divider direction="vertical" />
          <el-switch inline-prompt size="default" active-text="开启换行" inactive-text="关闭换行" v-model="warpRow" />
          <el-divider direction="vertical" />
        </div>
        <div>
          <el-divider direction="vertical" />
          <el-button type="primary" :icon="RefreshRight" @click="refreshEChart">图表</el-button>
          <el-button type="primary" :icon="RefreshRight" @click="doSearch()">查询</el-button>
          <el-button type="primary" :icon="RefreshLeft" @click="clearForm">重置</el-button>
          <el-button type="primary" :icon="Scissor" @click="showEsAnalyze">分词</el-button>
          <el-button type="primary" :icon="Document" @click="getLogSource">详情</el-button>
          <el-button type="primary" :icon="InfoFilled" @click="showQA">QA</el-button>
        </div>
      </div>

      <div class="table-operator-inputs">
        <el-input style="width: 100%;" v-model="tableParams.message" placeholder="日志内容"
          @keyup.enter.native="doSearch()" />
        <el-input style="width: 100%;" v-model="tableParams.notMessage" placeholder="排除内容"
          @keyup.enter.native="doSearch()" />
        <el-input style="width: 70px;" v-model="tableParams.logLevel" placeholder="日志级别"
          @keyup.enter.native="doSearch()" />
        <el-input style="width: 280px;" v-model="tableParams.traceId" placeholder="TraceId"
          @keyup.enter.native="doSearch()" />
        <el-input style="width: 180px;" v-model="tableParams.beginDate" placeholder="开始时间"
          @keyup.enter.native="doSearch()" />
        <el-input style="width: 180px;" v-model="tableParams.endDate" placeholder="结束时间"
          @keyup.enter.native="doSearch()" />
        <el-input style="width: 150px;" v-model="tableParams.appName" placeholder="应用名称"
          @keyup.enter.native="doSearch()" />
        <el-input style="width: 150px;" v-model="tableParams.indexName" placeholder="索引名称"
          @keyup.enter.native="doSearch()" />
        <div style="clear: both"></div>
      </div>
    </div>

    <el-divider style="border-bottom: 1px solid var(--el-color-primary-light-7);margin: 10px;"></el-divider>
    <div class="table">
      <el-table border height="100%" tooltip-effect="dark" v-loading="tableLoading" :data="tableDatas">
        <el-table-column prop="score" width="50" :show-overflow-tooltip="true" label="分数" />
        <el-table-column prop="datetime" width="185" label="时间" />
        <el-table-column prop="level" width="50" :show-overflow-tooltip="true" label="级别" align="center">
          <template #default="scope">
            <div v-html="scope.row.level"></div>
          </template>
        </el-table-column>
        <el-table-column prop="message" min-width="1000" :show-overflow-tooltip="!warpRow" label="日志">
          <template #default="scope">
            <div v-html="'[' + scope.row.traceId + '] ' +
              '[' + scope.row.thread + '] ' +
              '[' + scope.row.clazz + '] >>> ' +
              scope.row.message">
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="appName" width="120" label="应用名称" />
        <el-table-column prop="hostName" width="100" :show-overflow-tooltip=true label="节点" />
      </el-table>
    </div>

    <div class="table-pagination">
      <el-pagination background layout="prev, pager, next" @current-change="pageNumChange"
        :current-page="tableParams.pageNum" :page-size="tableParams.pageSize" :total="tableParams.total">
      </el-pagination>
      <div class="table-pagination-desc" style="margin-left: 20px">
        完成时间:{{ doneDatetime }}, 用时:{{ tookMs }}ms.
      </div>
    </div>
  </div>

  <el-dialog width="60%" v-model="qaShow" title="使用方式与常见问题" style="margin-top: 40px;">
    <logQA></logQA>
  </el-dialog>

  <el-dialog width="60%" v-model="analyzeShow" title="分词测试">
    <logAnalyze></logAnalyze>
  </el-dialog>
</template>

<script setup lang="ts">
import { useRoute } from 'vue-router'
import { ref, onMounted, nextTick } from "vue";
import { InfoFilled, Scissor, Document, RefreshLeft, RefreshRight } from '@element-plus/icons-vue';
import { logPageApi } from '@/api/log';
import { getNowTimeFormat } from "@/assets/utils/util";
import logQA from './LogQA.vue'
import logAnalyze from './LogAnalyze.vue'
import { isNotNull } from '@/assets/utils/obj';

const route = useRoute();

const intervalRefreshAll = ref(false);
const intervalRefreshAllTask = ref<any>()

const qaShow = ref(false);
const analyzeShow = ref(false);

const warpRow = ref(false);
const doneDatetime = ref();
const tookMs = ref();
const tableLoading = ref(false)
const tableDatas = ref()
const tableParams = ref({
  indexName: 'index_backend_log',
  traceId: '',
  matchOperator: false, // 全部匹配
  originMessage: false, // 显示原文
  highlight: true,  // 是否高亮
  sortTimestampDesc: true,  // 时间排序
  sortHitScoreDesc: false, // 分数排序
  beginDate: '',    // 开始时间
  endDate: '',    // 结束时间
  logLevel: '',    // 日志级别
  message: '',    // 包含内容
  notMessage: '',    // 排除内容
  appName: '',    // 应用名称
  pageNum: 1,
  pageSize: 25,
  totalCount: 0,
  totalPage: 0,
  total: 0
});

// -------------------- method
const sortHitScoreDescChange = (val: boolean) => {
  tableParams.value.sortHitScoreDesc = val;
  if (val) {
    tableParams.value.sortTimestampDesc = false
  }
}

const sortTimestampDescChange = (val: boolean) => {
  tableParams.value.sortTimestampDesc = val;
  if (val) {
    tableParams.value.sortHitScoreDesc = false
  }
}

const refreshAllTask = () => {
  console.log('定时刷新数据:', new Date());
  doSearch();
}
const refreshAllTaskStart = () => {
  clearInterval(intervalRefreshAllTask.value);
  intervalRefreshAllTask.value = setInterval(refreshAllTask, 10000);
  console.log('定时任务开始:', intervalRefreshAllTask.value)
}
const refreshAllTaskStop = () => {
  clearInterval(intervalRefreshAllTask.value);
  console.log('定时任务停止:', intervalRefreshAllTask.value)
}
const intervalRefreshAllChange = (val: boolean) => {
  if (val) {
    refreshAllTaskStart();
  } else {
    refreshAllTaskStop();
  }
}

const showQA = () => {
  if (qaShow.value === true) {
    qaShow.value = false;
  } else {
    qaShow.value = true;
  }
}

const showEsAnalyze = () => {
  if (analyzeShow.value === true) {
    analyzeShow.value = false;
  } else {
    analyzeShow.value = true;
  }
}

const clearForm = () => {
  tableParams.value = {
    indexName: 'index_backend_log',
    traceId: '',
    matchOperator: false, // 全部匹配
    originMessage: false, // 显示原文
    highlight: true,  // 是否高亮
    sortTimestampDesc: true,  // 时间排序
    sortHitScoreDesc: false, // 分数排序
    beginDate: '',    // 开始时间
    endDate: '',    // 结束时间
    logLevel: '',    // 日志级别
    message: '',    // 包含内容
    notMessage: '',    // 排除内容
    appName: '',    // 应用名称
    pageNum: 1,
    pageSize: 25,
    totalCount: 0,
    totalPage: 0,
    total: 0
  }
}

const getLogSource = () => {

}

const getLogPage = () => {
  tableLoading.value = true;
  let paramTem = { ...tableParams.value };
  // 对消息内容，排除内容进行URL编码，服务端需要解码
  paramTem.message = encodeURI(paramTem.message);
  paramTem.notMessage = encodeURI(paramTem.notMessage);
  logPageApi(paramTem).then((resp: any) => {
    tableParams.value.total = Number(resp.data.total);
    tableParams.value.totalPage = resp.data.totalPage;
    tookMs.value = resp.data.took || 0;
    tableDatas.value = resp.data.datas.map((item: any) => {
      if (item.traceId.length < 32) {
        item.traceId = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
      }

      if (item.thread.length > 25) {
        item.thread = item.thread.substring(item.thread.length - 25, item.thread.length);
      } else {
        let prefix = '<span style="white-space: pre">';
        for (let i = 0; i < 25 - item.thread.length; i++) {
          prefix += '#';
        }
        item.thread = prefix + '</span>' + item.thread;
      }

      if (item.clazz.length > 50) {
        item.clazz = item.clazz.substring(item.clazz.length - 50, item.clazz.length);
      } else {
        let prefix = '<span style="white-space: pre">';
        for (let i = 0; i < 50 - item.clazz.length; i++) {
          prefix += '#';
        }
        item.clazz = prefix + '</span>' + item.clazz;
      }

      item.level = item.level
        .replace("TRACE", "<span style='color: #0091ff;font-weight: 700;font-family: Consolas,Monaco;white-space: pre;'>TRACE</span>")
        .replace("DEBUG", "<span style='color: #3f8a10;font-weight: 700;font-family: Consolas,Monaco;white-space: pre;'>DEBUG</span>")
        .replace("INFO", "<span style='color: #c4bbbb;font-weight: 700;font-family: Consolas,Monaco;white-space: pre;'>INFO</span>")
        .replace("WARN", "<span style='color: #ab9336;font-weight: 700;font-family: Consolas,Monaco;white-space: pre;'>WARN</span>")
        .replace("ERROR", "<span style='color: #dd4c4c;font-weight: 700;font-family: Consolas,Monaco;white-space: pre;'>ERROR</span>");
      return item
    });
    doneDatetime.value = getNowTimeFormat();
  }).finally(() => {
    setTimeout(() => {
      tableLoading.value = false;
    }, 500);
  })
}

const pageNumChange = (val: number) => {
  tableParams.value.pageNum = val;
  getLogPage();
}

const doSearch = () => {
  tableParams.value.pageNum = 1;
  getLogPage();
}

const reload = () => {
  nextTick(() => {
    doSearch();
  })
}

const getRouteQueryParams = () => {
  let traceId = route.query.traceId;
  if (isNotNull(traceId)) {
    tableParams.value.traceId = traceId as string;
    tableParams.value.pageNum = 1
  }
}

onMounted(() => {
  getRouteQueryParams();
})

// ---------------- emits
const emits = defineEmits(['refreshChart'])
const refreshEChart = () => {
  emits('refreshChart')
}

defineExpose({
  reload
})

</script>

<style scoped lang="scss">
$height-log-search-container: 100px;
$height-log-table-pagination: 33px;

.table-log-root {
  @include box(100%, 100%);
  @include flex(column, flex-start, center);

  .table-container {
    @include flex(row, flex-start, center);
    @include box(100%, $height-log-search-container);

    .table-operator-btns {

      @include flex(column, flex-start, center);
      height: 100%;
      min-width: 500px;
      max-width: 500px;

      &>div {
        @include flex(row, flex-start, center);
        width: 100%;
        margin-left: 10px;
        margin-bottom: 8px;

        i {
          margin: 0 5px;
          cursor: pointer;
        }
      }
    }

    .table-operator-inputs {
      height: 100%;
      width: 100%;
      font-size: 12px;
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;

      .el-input {
        margin: 2px 3px;
      }
    }

  }

  .table {
    @include box(100%, calc(100% - 44px - #{$height-log-search-container} - #{$height-log-table-pagination}));

    :deep(.el-table--small .el-table__cell) {
      padding: 1px 0;
    }
  }

  .table-pagination {
    @include flex(row, flex-start, center);
    @include box(100%, $height-log-table-pagination);
    margin: 10px 0 0 0;

    .table-pagination-desc {
      @include font(14px);
      color: var(--el-color-primary);
      margin-left: 20px
    }
  }
}
</style>